#include "ti_msp_dl_config.h"
#include "../Driver/KEY/KEY.h"
#include "../Driver/CLOCK/clock.h"


// 全局按键句柄
KEY_Handle_t g_key_s3 = {0};

/**
 * @brief 按键初始化函数
 * @note GPIO配置已在ti_msp_dl_config.c中完成，此处仅初始化按键句柄
 */
void KEY_Init(void)
{
    // 初始化按键句柄
    g_key_s3.current_state = KEY_STATE_RELEASED;
    g_key_s3.last_state = KEY_STATE_RELEASED;
    g_key_s3.debounce_counter = 0;
    g_key_s3.press_counter = 0;
    g_key_s3.long_press_triggered = false;
    g_key_s3.event = KEY_EVENT_NONE;
    
    // 清除可能存在的中断标志
    DL_GPIO_clearInterruptStatus(KEY_S3_PORT, KEY_S3_PIN);
}

/**
 * @brief 读取按键物理状态
 * @return true: 按键按下, false: 按键释放
 */
static bool KEY_ReadPhysicalState(void)
{
    // 读取GPIO状态，由于配置了上拉电阻，按下时为低电平
    return (DL_GPIO_readPins(KEY_S3_PORT, KEY_S3_PIN) == 0);
}

/**
 * @brief 按键扫描函数(需要定时调用)
 * @note 建议每10ms调用一次
 */
void KEY_Scan(void)
{
    bool current_physical_state = KEY_ReadPhysicalState();
    
    // 状态机处理
    switch (g_key_s3.current_state) {
        case KEY_STATE_RELEASED:
            if (current_physical_state) {
                // 检测到按键按下，进入防抖状态
                g_key_s3.current_state = KEY_STATE_DEBOUNCING;
                g_key_s3.debounce_counter = 0;
            }
            break;
            
        case KEY_STATE_DEBOUNCING:
            if (current_physical_state) {
                g_key_s3.debounce_counter++;
                if (g_key_s3.debounce_counter >= (KEY_DEBOUNCE_TIME_MS / KEY_SCAN_INTERVAL_MS)) {
                    // 防抖完成，确认按键按下
                    g_key_s3.current_state = KEY_STATE_PRESSED;
                    g_key_s3.press_counter = 0;
                    g_key_s3.long_press_triggered = false;
                    g_key_s3.event = KEY_EVENT_PRESS;
                }
            } else {
                // 抖动，返回释放状态
                g_key_s3.current_state = KEY_STATE_RELEASED;
                g_key_s3.debounce_counter = 0;
            }
            break;
            
        case KEY_STATE_PRESSED:
            if (current_physical_state) {
                // 按键持续按下
                g_key_s3.press_counter++;
                
                // 检查长按
                if (!g_key_s3.long_press_triggered && 
                    g_key_s3.press_counter >= (KEY_LONG_PRESS_TIME_MS / KEY_SCAN_INTERVAL_MS)) {
                    g_key_s3.long_press_triggered = true;
                    g_key_s3.event = KEY_EVENT_LONG_PRESS;
                }
            } else {
                // 按键释放
                g_key_s3.current_state = KEY_STATE_RELEASED;
                g_key_s3.press_counter = 0;
                g_key_s3.event = KEY_EVENT_RELEASE;
            }
            break;
            
        default:
            g_key_s3.current_state = KEY_STATE_RELEASED;
            break;
    }
    
    g_key_s3.last_state = g_key_s3.current_state;
}

/**
 * @brief 获取按键事件
 * @return KEY_Event_t 按键事件类型
 */
KEY_Event_t KEY_GetEvent(void)
{
    return g_key_s3.event;
}

/**
 * @brief 检查按键是否处于按下状态
 * @return true: 按键按下, false: 按键释放
 */
bool KEY_IsPressed(void)
{
    return (g_key_s3.current_state == KEY_STATE_PRESSED);
}

/**
 * @brief 清除按键事件
 */
void KEY_ClearEvent(void)
{
    g_key_s3.event = KEY_EVENT_NONE;
}

/**
 * @brief 按键中断处理函数
 * @note 在主程序的GPIOB中断处理函数中调用此函数
 */
void KEY_IRQHandler(void)
{
    // 检查是否为按键S3中断
    if (DL_GPIO_getEnabledInterruptStatus(KEY_S3_PORT, KEY_S3_PIN)) {
        // 清除中断标志
        DL_GPIO_clearInterruptStatus(KEY_S3_PORT, KEY_S3_PIN);
        
        // 中断方式主要用于唤醒系统或快速响应
        // 具体的按键处理仍然依赖于KEY_Scan()函数的状态机
        // 这里可以设置一个标志或执行简单的处理
    }
}

/**
 * @brief 按键去抖动延时
 * @param ms 延时毫秒数
 */
static void KEY_DelayMs(uint32_t ms)
{
    // 使用系统时钟进行简单延时
    uint32_t cycles = ms * (CPUCLK_FREQ / 1000);
    delay_cycles(cycles);
}

/**
 * @brief 阻塞式按键检测(简化版本)
 * @return true: 检测到按键按下, false: 超时或无按键
 * @note 此函数会阻塞程序执行，建议使用非阻塞的KEY_Scan()函数
 */
bool KEY_WaitForPress(uint32_t timeout_ms)
{
    uint32_t count = 0;
    
    while (count < timeout_ms) {
        if (KEY_ReadPhysicalState()) {
            // 简单防抖
            KEY_DelayMs(KEY_DEBOUNCE_TIME_MS);
            if (KEY_ReadPhysicalState()) {
                return true;
            }
        }
        KEY_DelayMs(1);
        count++;
    }
    
    return false;
}

/**
 * @brief 等待按键释放
 */
void KEY_WaitForRelease(void)
{
    while (KEY_ReadPhysicalState()) {
        KEY_DelayMs(10);
    }
    // 额外延时确保完全释放
    KEY_DelayMs(KEY_DEBOUNCE_TIME_MS);
}
